package com.simonall.access.dao.impl;

import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.persistence.Table;

import org.hibernate.Session;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.Query;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;

import com.simonall.constant.SQL;

@SuppressWarnings("unchecked")
public abstract class AbstractBaseDao<T> extends HibernateDaoSupport {

	public Class<T> clazz;

	public AbstractBaseDao() {
		super();
		Type type = getClass().getGenericSuperclass();
		ParameterizedType parameterizedType = (ParameterizedType) type;
		this.clazz = (Class<T>) parameterizedType.getActualTypeArguments()[0];
	}

	/**
	 * REMOVE FROM 前面的语句
	 * 
	 * @param statement 查询语句
	 * @return
	 */
	public final String removeFromBefore(StringBuilder statement) {
		int beginPos = String.valueOf(statement).toUpperCase().indexOf(SQL.FROM.trim());
		return statement.substring(beginPos);
	}

	/**
	 * REMOVE ORDER BY子句
	 * 
	 * @param statement 查询语句
	 * @return
	 */
	public final StringBuilder removeOrder(StringBuilder statement) {
		Pattern p = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*", Pattern.CASE_INSENSITIVE);
		Matcher m = p.matcher(String.valueOf(statement));
		StringBuffer buffer = new StringBuffer();
		while (m.find()) {
			m.appendReplacement(buffer, "");
		}
		m.appendTail(buffer);
		return new StringBuilder(buffer);
	}

	/**
	 * 获取当前实体对应的表名
	 * 
	 * @return
	 */
	public final String getTableName() {
		Annotation[] annotation = clazz.getAnnotations();
		for (Annotation tation : annotation) {
			if (tation instanceof Table) {
				return ((Table) tation).name();
			}
		}
		return null;
	}

	public final Query<T> hqlQuery(CharSequence statement, Map<String, Object> values) {
		Query<T> query = super.currentSession().createQuery(statement.toString());
		if (values != null && values.size() > 0) {
			Set<String> keys = values.keySet();
			for (String key : keys) {
				query.setParameter(key, values.get(key));
			}
		}
		return query;
	}

	public final NativeQuery<?> sqlQuery(CharSequence statement, Map<String, Object> values) {
		Session session = super.currentSession();
		NativeQuery<?> nativeQuery = session.createNativeQuery(statement.toString());
		if (values != null && values.size() > 0) {
			Set<String> keys = values.keySet();
			for (String key : keys) {
				nativeQuery.setParameter(key, values.get(key));
			}
		}
		return nativeQuery;
	}

	public final NativeQuery<T> entitySqlQuery(CharSequence statement, Map<String, Object> values) {
		Session session = super.currentSession();
		NativeQuery<T> nativeQuery = session.createNativeQuery(statement.toString(), clazz);
		if (values != null && values.size() > 0) {
			Set<String> keys = values.keySet();
			for (String key : keys) {
				nativeQuery.setParameter(key, values.get(key));
			}
		}
		return nativeQuery;
	}

}
